package com.itheima.app.manager;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.*;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.mongo.CommentService;
import com.itheima.service.mongo.FocusUserService;
import com.itheima.service.mongo.MovementService;
import com.itheima.service.mongo.VideoService;
import com.itheima.util.ConstantUtil;
import com.itheima.vo.CommentVo;
import com.itheima.vo.PageBeanVo;
import com.itheima.vo.VideoVo;
import com.itheima.vo.VoiceVo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class VideoManager {

    @DubboReference
    VideoService videoService;

    @DubboReference
    UserInfoService userInfoService;

    @Autowired
    FastFileStorageClient client;

    @Autowired
    FdfsWebServer server;

    @DubboReference
    FocusUserService focusUserService;

    @DubboReference
    CommentService commentService;

    @DubboReference
    MovementService movementService;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    /*
        value:名称空间
        key:缓存中的key   用户id_页码_每页条数
        unless:当查询的页面中的数据为空的时候就不缓存
     */
    @Cacheable(value = "tanhua",key = "#userId+'_'+#pageNum+'_'+#pageSize",unless = "#result.counts==0" )
    public PageBeanVo findRecommendVideoByPage(Long userId, Integer pageNum, Integer pageSize) {
        //1.获取登陆者id
        //2.调用service获取PageBeanVo
        PageBeanVo pageBeanVo = videoService.findRecommendVideoByPage(userId, pageNum, pageSize);

        //3.从pageBeanVo中获取视频列表
        List<Video> items = (List<Video>) pageBeanVo.getItems();

        //4.遍历视频列表,获取每个视频的发布人id,查询其userInfo,将视频和userInfo封装videoVo对象,将每个vo对方放入预先声明好的voList中
        List<VideoVo> voList = new ArrayList<>();
        if (CollUtil.isNotEmpty(items)) {
            items.forEach(video -> {
                Long videoUserId = video.getUserId();
                UserInfo userInfo = userInfoService.findById(videoUserId);

                VideoVo vo = new VideoVo();
                //注意:先封装userInfo,后封装video,最终vo中的id为视频id
                vo.setUserInfo(userInfo);
                vo.setVideo(video);

                //判断用户是否关注过
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.FOCUS_USER,userId,videoUserId))) {
                    vo.setHasFocus(1);
                }

                voList.add(vo);
            });
        }

        //5.将voList设置给pageBeanVo
        pageBeanVo.setItems(voList);

        //6.返回pageBeanVo即可
        return pageBeanVo;
    }

    //@CacheEvict(value = "tanhua",allEntries = true)
    //加上笔记中的三个类之后就可以使用通配符删除指定用户的缓存了
    @CacheEvict(value = "tanhua",key = "#userId+'_*'")
    public void save(Long userId, MultipartFile videoThumbnail, MultipartFile videoFile) throws IOException {
        //1.上传俩文件到fdfs上,获取俩路径
        StorePath coverPath = client.uploadFile(videoThumbnail.getInputStream(), videoThumbnail.getSize(),
                FileUtil.extName(videoThumbnail.getOriginalFilename()), null);
        StorePath videoPath = client.uploadFile(videoFile.getInputStream(), videoFile.getSize(),
                FileUtil.extName(videoFile.getOriginalFilename()), null);

        //2.封装video(userId,图片路径,视频路径...)
        Video video = new Video();
        video.setCreated(System.currentTimeMillis());
        video.setUserId(userId);
        video.setText("犯我中华者,虽远必诛!");
        video.setPicUrl(server.getWebServerUrl()+coverPath.getFullPath());
        video.setVideoUrl(server.getWebServerUrl()+videoPath.getFullPath());

        System.out.println(video.getVideoUrl());
        System.out.println(video.getPicUrl());

        //3.调用service完成保存操作
        videoService.save(video);
    }

    //@CacheEvict(value = "tanhua",allEntries = true)
    //加上笔记中的三个类之后就可以使用通配符删除指定用户的缓存了
    @CacheEvict(value = "tanhua",key = "#userId+'_*'")
    public void focusUser(Long userId, Long focusUserId) {
        //1.封装focusUser
        FocusUser focusUser = new FocusUser();
        focusUser.setUserId(userId);
        focusUser.setFocusUserId(focusUserId);
        focusUser.setCreated(System.currentTimeMillis());

        //2.调用service完成保存操作
        focusUserService.save(focusUser);

        //3.往redis中保存关注的标识
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.FOCUS_USER,userId,focusUserId),"1");
    }

    //@CacheEvict(value = "tanhua",allEntries = true)
    //加上笔记中的三个类之后就可以使用通配符删除指定用户的缓存了
    @CacheEvict(value = "tanhua",key = "#userId+'_*'")
    public void unFocusUser(Long userId, Long focusUserId) {
        //1.调用service完成删除操作
        focusUserService.delete(userId,focusUserId);
        //2.从redis中删除关注的标识
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.FOCUS_USER,userId,focusUserId));
    }

    //对视频点赞
    public ResponseEntity videoLike(String publishId) {
        //1.获取登陆者id
        Long userId = UserHolder.get().getId();

        //2.通过动态id查询动态对象
        Video videoUser = videoService.findById(new ObjectId(publishId));

        //3.封装video对象
        Video video = new Video();
        video.setCreated(System.currentTimeMillis());
        video.setUserId(videoUser.getUserId());
        video.setText(videoUser.getText());
        video.setPicUrl(video.getPicUrl());
        video.setVideoUrl(video.getVideoUrl());

        //4.远程调用service完成保存操作
          int count =videoService.save(video);

        //5.往redis中保存当前用户的操作  key: video_like:用户id_动态id     value:1
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.VIDEO_LIKE,userId,publishId),"1");

        return ResponseEntity.ok(count);
    }

    //取消点赞
    public ResponseEntity videoDislike(String publishId) {
        //1.获取登陆者id
        Long userId = UserHolder.get().getId();

        //2.远程调用service完成操作
        int count = commentService.delete(userId, new ObjectId(publishId), 4);

        //3.删除redis中用户操作的标识
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.VIDEO_LIKE,userId,publishId));

        //6.将用户的行为得分放入mq中
        return ResponseEntity.ok(count);
    }




    public ResponseEntity findCommentByPage2(String publishId, Integer pageNum, Integer pageSize) {
        //1.远程调用service查询pageBeanVo
        PageBeanVo pageBeanVo = commentService.findCommentByPage2(new ObjectId(publishId), pageNum, pageSize);

        //2.获取pageBeanVo中评论集合
        List<Comment> items = (List<Comment>) pageBeanVo.getItems();

        //3.遍历评论集合,获取每个评论,调用service查询评论发布人的userInfo,将userInfo和评论封装成commentVo,且将每个vo放入一个声明好的voList中
        //3.1 声明voList,存放返回的数据集合
        List<CommentVo> voList = new ArrayList<>();

        //3.2 遍历评论集合,获取每个评论,
        if (CollUtil.isNotEmpty(items)) {
            items.forEach(comment -> {
                //3.3 调用service查询评论发布人的userInfo
                UserInfo userInfo = userInfoService.findById(comment.getUserId());

                //3.4 将userInfo和评论封装成commentVo
                CommentVo vo = new CommentVo();
                vo.setId(comment.getId().toString());

                vo.setAvatar(userInfo.getAvatar());
                vo.setNickname(userInfo.getNickname());

                vo.setContent(comment.getContent());
                //使用hutool中工具类
                vo.setCreateDate(DateUtil.formatDateTime(new Date(comment.getCreated())));

                //TODO 实战的时候大家可以完成对评论的点赞

                //3.5 且将每个vo放入voList中
                voList.add(vo);
            });
        }

        //4.将voList封给pageBeanVo
        pageBeanVo.setItems(voList);

        //5.返回pageBeanVo
        return ResponseEntity.ok(pageBeanVo);
    }

    public void videoComment(String videoId, String content) {
        //1.获取登陆者id
        Long userId = UserHolder.get().getId();

        //2.通过动态id查询动态对象
        Video video = videoService.findById(new ObjectId(videoId));

        //3.封装comment对象
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis());
        comment.setPublishId(new ObjectId(videoId));
        comment.setCommentType(5);
        comment.setUserId(userId);
        comment.setPublishUserId(video.getUserId());
        comment.setContent(content);

        //4.远程调用service完成保存操作
        commentService.save(comment);

    }

    //视频评论点赞
    public ResponseEntity videoCommentLike(String publishId) {   //publishId是视频评论人的id
        //1.获取登陆者id
        Long userId = UserHolder.get().getId();

        //2.通过动态id查询视频评论对象
        Comment comment1 = commentService.findCommentById(new ObjectId(publishId));

        //3.封装comment对象
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis());
        comment.setPublishId(new ObjectId(publishId));
        comment.setCommentType(6);
        comment.setUserId(userId);
        comment.setPublishUserId(comment1.getPublishUserId());

        //4.远程调用service完成保存操作
        int count = commentService.save(comment);

        //5.往redis中保存当前用户的操作  key: video_like:用户id_动态id     value:1
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.VIDEO_LIKE,userId,publishId),"1");

        return ResponseEntity.ok(count);
    }

    //取消视频评论点赞
    public ResponseEntity videoCommentDislike(String publishId) {
        //1.获取登陆者id
        Long userId = UserHolder.get().getId();

        //2.远程调用service完成操作
        int count = commentService.delete(userId, new ObjectId(publishId), 6);

        //3.删除redis中用户操作的标识
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.VIDEO_LIKE,userId,publishId));

        //6.将用户的行为得分放入mq中
        return ResponseEntity.ok(count);
    }


    public void add(Long userId, MultipartFile soundFile) throws IOException {
        StorePath voicePath = client.uploadFile(soundFile.getInputStream(), soundFile.getSize(),
                FileUtil.extName(soundFile.getOriginalFilename()), null);

        Voice voice = new Voice();
        voice.setUserId(userId);
        voice.setCreated(System.currentTimeMillis());
        voice.setVoiceUrl(server.getWebServerUrl()+voicePath.getFullPath());

        videoService.add(voice);
    }


    public ResponseEntity find() {
        Long toUserId = UserHolder.get().getId();

        Voice voice = videoService.findall(toUserId);

        if(voice!=null){

            UserInfo userInfo = userInfoService.findById(voice.getUserId());
            VoiceVo voiceVo = new VoiceVo();
            voiceVo.setUserInfo(userInfo);
            voiceVo.setSoundUrl(voice.getVoiceUrl());

            if(stringRedisTemplate.hasKey("toUserId :" + toUserId)){
                stringRedisTemplate.opsForValue().decrement("toUserId :" + toUserId);
                Integer count = Integer.valueOf(stringRedisTemplate.opsForValue().get("toUserId :" + toUserId));
                if(count > 0){
                    voiceVo.setRemainingTimes(count);
                }else {
                    voiceVo.setRemainingTimes(0);
                }
            }else {
                stringRedisTemplate.opsForValue().set("toUserId :" + toUserId, "8", 24, TimeUnit.HOURS);
            }
            return ResponseEntity.ok(voiceVo);
        }
        return null;
    }


}
